package com.exmple.myapplication;

import android.content.Context;
import android.content.SharedPreferences;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import androidx.activity.result.ActivityResultCallback;
import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;

import java.text.SimpleDateFormat;
import java.util.List;
import java.util.Locale;

import jp.co.canon.android.print.ij.usbsdk.CanonPermissionRequestCallback;
import jp.co.canon.android.print.ij.usbsdk.CanonPreparationCallback;
import jp.co.canon.android.print.ij.usbsdk.CanonPrintCallback;
import jp.co.canon.android.print.ij.usbsdk.CanonPrintDevice;
import jp.co.canon.android.print.ij.usbsdk.CanonPrintJob;
import jp.co.canon.android.print.ij.usbsdk.CanonPrintParams;
import jp.co.canon.android.print.ij.usbsdk.CanonPrinterStatus;
import jp.co.canon.android.print.ij.usbsdk.CanonUsbManager;
//精简调用佳能打印机
public class PrintFragment extends Fragment {
    private CanonPrintJob mJob;
    private CanonPrintDevice mSelectedPrinter;
    private final String TAG = getClass().getSimpleName();
    private ActivityResultLauncher<String> resultLauncher;
    private SharedPreferences sharedPreferences;
    private final String KEY_STR = "selectPath";
    private TextView textPath;
    private Uri mSelectedFile;
    private final SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMddHHmmss", Locale.CHINA);
    private boolean isPrinting;
    private final Handler mHandler = new Handler(Looper.myLooper());
    private TextView tvPath;

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        resultLauncher = registerForActivityResult(new ActivityResultContracts.GetContent(), new ActivityResultCallback<Uri>() {
            @Override
            public void onActivityResult(Uri result) {
                if (result==null||result==Uri.EMPTY)
                    return;
                mSelectedFile = result;
                tvPath.setText(ReaderUtils.getImageAbsolutePath(getContext(),result));
            }
        });

    }

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        getPrinterList();
        View rootView = inflater.inflate(R.layout.fragment_print, null);
        tvPath = rootView.findViewById(R.id.tv_path);
        rootView.findViewById(R.id.button_Print).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                resultLauncher.launch("*/*");
            }
        });
        rootView.findViewById(R.id.button_Print_4).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                executePrint();
            }
        });
        return rootView;

    }


    private void getPrinterList() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                final Context applicationContext = getActivity().getApplicationContext();

                try {
                    List<CanonPrintDevice> printerList = CanonUsbManager.getPrinterList(applicationContext);
                    selectPrinter(printerList);
                } catch (SecurityException e) {
                    CanonUsbManager.prepareToGetPrinterList(applicationContext, new CanonPreparationCallback() {
                        @Override
                        public void onSuccess() {
                            List<CanonPrintDevice> printerList = CanonUsbManager.getPrinterList(applicationContext);
                            selectPrinter(printerList);
                        }

                        @Override
                        public void onFailure() {
                            Log.i("onFailure: ", "获取打印机列表失败。");
                        }
                    });
                }
            }
        }).start();

    }

    private void selectPrinter(List<CanonPrintDevice> canonPrinterList) {
        if (canonPrinterList != null && canonPrinterList.size() > 0) {
            final CanonPrintDevice selected = canonPrinterList.get(0);

            if (CanonUsbManager.hasPermission(this.getActivity().getApplicationContext(), selected)) {
                mSelectedPrinter = selected;
                mJob = createJob();
            } else {
                boolean result = CanonUsbManager.requestPermission(
                        this.getActivity().getApplicationContext(),
                        selected,
                        new CanonPermissionRequestCallback() {
                            @Override
                            public void onReceivePermissionGranted(CanonPrintDevice device, boolean isGranted) {
                                if (selected.equals(device)) {
                                    mSelectedPrinter = device;
                                    mJob = createJob();

                                }
                            }
                        }
                );
                if (!result) {
                    Log.i("onFailure:", getString(R.string.failed_to_request_permission));
                }
            }

        }
    }

    private CanonPrintJob createJob() {
        CanonPrintJob job = new CanonPrintJob();
        if (mSelectedPrinter != null) {
            job.setDefaultPrintConfiguration(this.getActivity().getApplicationContext(), mSelectedPrinter);
            job.setPrintConfiguration(CanonPrintJob.Configuration.MediaType, 1);
            job.setPrintConfiguration(CanonPrintJob.Configuration.PaperSize, 3);
            job.setPrintConfiguration(CanonPrintJob.Configuration.Borderless, 1);
        }
        return job;
    }

    private void executePrint() {
        final Context applicationContext = this.getActivity().getApplicationContext();
if (isPrinting)
    return;
        if (mSelectedPrinter == null) {
            Log.i(TAG, getString(R.string.printer_is_not_selected));
            return;
        }

        if (mSelectedFile == null || mSelectedFile == Uri.EMPTY) {
            Log.i(TAG, getString(R.string.file_is_not_selected));
            return;
        }

        // Check the width and height of custom paper size
        if (mJob.getPrintConfiguration(CanonPrintJob.Configuration.PaperSize) == CanonPrintParams.PAPERSIZE_USERDEFINITION) {
            return;
        }

        // ManualDuplex setting
        mJob.setPrintConfiguration(CanonPrintJob.Configuration.ManualDuplex, CanonPrintParams.MANUAL_DUPLEX_SETTING_OFF);

        // Checks print configuration
        CanonPrintDevice.PrintableStatus checkStatus = mSelectedPrinter.isPrintableConfiguration(mJob);
        if (checkStatus != CanonPrintDevice.PrintableStatus.OK) {
            String checkMsg;
            switch (checkStatus) {
                case CONFLICT_BORDERLESS:
                    checkMsg = "无边距设置与所设介质和尺寸不匹配";
                    break;
                case CONFLICT_COLOR:
                    checkMsg = "色彩设置与所设介质不匹配";
                    break;
                case CONFLICT_DUPLEX:
                    checkMsg = "双面设置与所设介质和尺寸不匹配";
                    break;
                case CONFLICT_QUALITY:
                    checkMsg = "质量设置与所设介质不匹配";
                    break;
                case INAPPLICABLE_MEDIA:
                    checkMsg = "不适用的介质";
                    break;
                case INAPPLICABLE_SIZE:
                    checkMsg = "不适用的纸张尺寸";
                    break;
                case INAPPLICABLE_COPIES:
                    checkMsg = "不适用的打印份数";
                    break;
                case NULL_CAPABILITY:
                    checkMsg = "打印机能力获取失败";
                    break;
                case ERROR_CONFIGURATION:
                    checkMsg = "打印机配置错误";
                    break;
                case ERROR_USER_DEFINITION:
                    checkMsg = "自定义用纸尺寸设置错误";
                    break;
                default:
                    checkMsg = "其他无效的打印设置";
                    break;
            }
            Log.e(TAG, checkMsg);
            return;
        }

        // Disables/enables buttons
        isPrinting = true;
        if (CanonUsbManager.hasPermission(applicationContext, mSelectedPrinter)) {
            print(mSelectedPrinter);
        } else {
            boolean result = CanonUsbManager.requestPermission(
                    applicationContext,
                    mSelectedPrinter,
                    new CanonPermissionRequestCallback() {
                        @Override
                        public void onReceivePermissionGranted(CanonPrintDevice device, boolean isGranted) {
                            if (mSelectedPrinter.equals(device)) {
                                if (isGranted) {
                                    print(device);
                                } else {
                                    isPrinting = false;
                                    Log.e(TAG, getString(R.string.printer_is_not_granted));
                                }
                            }
                        }
                    }
            );
            if (!result) {
                isPrinting = false;
                Log.e(TAG, getString(R.string.failed_to_request_permission));
            }
        }
    }

    private void print(@NonNull final CanonPrintDevice printer) {
        // Sets a print file
        mJob.setPrintFile(mSelectedFile, CanonPrintParams.PAPERORIENTATION_AUTOMATIC, CanonPrintParams.SCALING_NONE, this.getActivity().getApplicationContext());


        // Executes printing
        if (!printer.print(mJob, new CanonPrintCallback() {
            @Override
            public void onChangedJobStatus(final CanonPrintJob job) {
                final CanonPrintJob.PrintJobStatus changedJobStatus = job.getStatus();
                mHandler.post(() -> {
                    String printedCountInfo = getString(R.string.printed_count_info,
                            job.getTotalPrintedCopy(),
                            job.getPrintConfiguration(CanonPrintJob.Configuration.Copies),
                            job.getTotalPrintedPage(),
                            job.getTotalPage()
                    );
                    Log.i(TAG, "onChangedJobStatus: " + getString(R.string.job_status,
                            updateJobStatusTexts(changedJobStatus.ordinal()),
                            String.format(Locale.ENGLISH, "%3.2f", (float) (job.getJobProgress() * 100.0f)),
                            printedCountInfo
                    ));

                    // Initializes the text to "Ready" when job has been finished
                    if (job.isFinished()) {
                        // Re-creates a job
                        mJob = createJob();
                    }
                });
            }

            @Override
            public void onChangedPrinterStatus(CanonPrintJob job, final CanonPrinterStatus status) {
                mHandler.post(() -> {
                    // Just shows the current status
                    String text = updateDeviceStatusTexts(status.getStatus().ordinal());
                    if (!status.getSupportCode().isEmpty()) {
                        text += getString(R.string.support_code, status.getSupportCode());
                    }
                    Log.i(TAG, "onChangedPrinterStatus: " + text);
                });
            }
        })) {
            mJob = createJob();
            Log.e(TAG, "打印失败");
        }
    }

    private String updateJobStatusTexts(int index) {
        String[] jobStatusNames = this.getContext().getResources().getStringArray(R.array.job_status);
        if (index > jobStatusNames.length) {
            return "";
        }
        return jobStatusNames[index];
    }

    private String updateDeviceStatusTexts(int index) {
        String[] deviceStatusNames = this.getActivity().getApplicationContext().getResources().getStringArray(R.array.device_status);
        if (index > deviceStatusNames.length) {
            return "";
        }
        return deviceStatusNames[index];
    }
}
